main_root = './';

addpath(genpath([ pwd ]))

%feature_string = 'l';
feature_string = 'lvrgshcbou';

training_video = 'GOPR2384_cab';

test_video{1} = 'GOPR2382_cab';
test_video{2} = 'GOPR2393_cab';

f_start = 150;
f_end = 11200;
f_rate = 25;

test_start{1} = 150;
test_end{1} = 5300;
test_rate{1} = 50;

test_start{2} = 20;
test_end{2} = 3100;
test_rate{2} = 20;


num_treebagger = 20;

downsample_rate = 0.5;

predownsample_rate = 0.05;

root = './../_FGS/';

    temp = dlmread('bagging_config.txt');

    max_bag_num = temp(1);

    clear temp;

%%
if 0
    for i = 1:3
        running_string = [main_root 'RBMTraining ' ,...
            '-a ', '-f ', root ,  ' -t ', training_video,...
            ' -p ', training_video, ' -v ', feature_string,...
            ' -s ', num2str(f_start + f_rate*(i-1)),...
            ' -e ', num2str(f_end + f_rate*(i-1)), ...
            ' -r ', num2str(f_rate*3)]

    
        system([running_string ' -z _train_part' num2str(i)]);
    end

    %%
    for i = 1:length(test_video)
        running_string = [main_root 'RBMTraining ' ,...
        '-a ', '-f ', root ,  ' -t ', test_video{i} ,...
        ' -p ', test_video{i}, ' -v ', feature_string,...
        ' -s ', num2str(test_start{i} ),...
        ' -e ', num2str(test_end{i} ), ...
        ' -r ', num2str(test_rate{i})];

        system([running_string ' -z _test_part' num2str(i)]);
    end
end
%%

clear feat_train
feat_valid = [];
clear feat_test

clear lab_train
lab_valid = [];
clear lab_test

disp('load data...' )
tic

for i = 1:max_bag_num

	disp([num2str(i) '/' num2str(max_bag_num)])
	
    feat_train_1 = getMat([main_root 'temp_feature_' num2str(i-1) '_' ...
        feature_string '_train_part' num2str(1) '.bin']);    
    
    feat_train_2 = getMat([main_root 'temp_feature_' num2str(i-1) '_' ...
        feature_string '_train_part' num2str(2) '.bin']);
    
    feat_valid = [feat_valid;getMat([main_root 'temp_feature_' num2str(i-1) '_' ...
        feature_string '_train_part' num2str(3) '.bin'])];
    
    feat_train{i} = [feat_train_1;feat_train_2];
    
    clear feat_train_1
    clear feat_train_2
    
    lab_train_1 = getMat([main_root 'temp_label_' num2str(i-1) '_' ...
        feature_string '_train_part' num2str(1) '.bin']);    
    
    lab_train_2 = getMat([main_root 'temp_label_' num2str(i-1) '_' ...
        feature_string '_train_part' num2str(2) '.bin']);
    
    lab_train{i} = [lab_train_1;lab_train_2];
    
    clear lab_train_1
    clear lab_train_2
    
    lab_valid = [lab_valid;getMat([main_root 'temp_label_' num2str(i-1) '_' ...
        feature_string '_train_part' num2str(3) '.bin'])];
    
    for j = 1:length(test_video)
        feat_test{i,j} = getMat([main_root 'temp_feature_' num2str(i-1) '_' ...
            feature_string '_test_part' num2str(j) '.bin']);
        
        lab_test{i,j} = getMat([main_root 'temp_label_' num2str(i-1) '_' ...
            feature_string '_test_part' num2str(j) '.bin']);
    end
end

toc

%%

n = size(feat_valid,1);
ord = randperm(n);
ord = ord( 1:floor(predownsample_rate*n));

feat_valid = feat_valid(ord,:);
lab_valid =  lab_valid(ord,:);

for i = 1:max_bag_num

	disp(['pre_down_sample_' num2str(i) '/' num2str(max_bag_num)])
    
    n = size(feat_train{i},1);
    ord = randperm(n);
    ord = ord( 1:floor(predownsample_rate*n));

    feat_train{i} = feat_train{i}(ord,:);
    lab_train{i} =  lab_train{i}(ord,:);	                    
            
    
    for j = 1:length(test_video)
        
        n = size(feat_test{i,j},1);
        ord = randperm(n);
        ord = ord( 1:floor(predownsample_rate*n));
    
        feat_test{i,j} = feat_test{i,j}( ord,:);
        lab_test{i,j}  =  lab_test{i,j}( ord,:);        
    end
end

%%

%Initialize Matlab Parallel Computing Enviornment by Xaero | Macro2.cn

CoreNum=8; %set CPU number

if matlabpool('size')<=0 %if the paralle is starting
    matlabpool('open','local',CoreNum); 
else
    disp('Already initialized'); 
end

try
    matlabpool open local 2;
catch
end

dims = size(feat_train{1},2);

disp(['feature selection on ' num2str(dims) ' dimension'])

sel_id = [];

if_in_sel = zeros(1,dims);

step_time = 10;

score_record = dlmread('report_feature_selection.txt');

sel_id = score_record(1:6,end)';

if_in_sel(sel_id) = 1;

%score_record = zeros(dims, 1+length(test_video)+1);
%f_on_valid, f_on_test , feature_id

for epoch_id = length(sel_id)+1:dims
    
    score_on_feat = zeros(1,dims);
    
    for cand_id = 1 : dims
        
        if( if_in_sel( cand_id)>0), continue, end
        
        tic
        
        temp_sel = [sel_id cand_id];
        
        for i = 1:max_bag_num
            n = size(feat_train{i},1);
            ord = randperm(n);
            ord = ord(1:floor(n*downsample_rate));
            temp_feat_train{i} = feat_train{i}( ord,temp_sel);
            temp_lab_train{i} = lab_train{i}(ord);
        end
        
        temp_feat_valid = feat_valid(:, temp_sel);
        
        clear bag
        
                
        disp('train random trees')                
        
        bag{max_bag_num} = [];
        
        
        
        parfor i = 1:max_bag_num                    
            warning off
            opt = statset('UseParallel','always');            
            temp_bag = TreeBagger(num_treebagger, ...
                temp_feat_train{i}, temp_lab_train{i},'Options',opt);
            bag{i} = temp_bag;
            warning on
        end
        
        
                        
        
        disp(['try add feature ' num2str(cand_id) ...
            ' in epoch ' num2str(epoch_id)])
                
        
        f_on_this_feat = zeros(1,max_bag_num);
        
        sum_lab_valid = sum( lab_valid );
        
        t_lab_valid = lab_valid==1;
        
        parfor i = 1:max_bag_num
            temp_i = i;
            res_str = bag{temp_i}.predict( temp_feat_valid);
            n = length(res_str);
            res = zeros(1,n);
            for j = 1:n
                res(j) = str2num(res_str{j});    
            end
            tp = sum(res(t_lab_valid));
            precision = tp / (sum( res)+1e-3);
            recall = tp / sum_lab_valid;
            f_on_this_feat(i) = precision * 2 * recall ...
                / (recall + precision +1e-3);
       end                
        
        disp([ 'F_1 is ' num2str(mean(f_on_this_feat)) ...
            ' ~ ' num2str(std(f_on_this_feat))])
        
        score_on_feat(cand_id) = mean(f_on_this_feat);
        
        step_time = toc*0.1 + step_time* 0.9;
        
        disp(['step_time ' num2str(step_time)])
        
        if(mod( cand_id, 5)==0)
        
            epoch_time = step_time * (dims- epoch_id+1);


            disp(['estimate time for epoch ' ...
                   ,num2str(epoch_time)]);

            disp([ num2str( step_time * (dims- epoch_id+1-cand_id)) ...
                ' rest for this epoch' ])

            disp([num2str(epoch_time * (dims - epoch_id )*.6/3600) ...            
                ,' hours rest for whole experiment'] )                                        
        end
    end
    
    [score_valid, max_cand_id ] = max( score_on_feat );        
    
    if_in_sel( max_cand_id ) = 1;
    
    disp('===============')
    disp(['feature id ' num2str(max_cand_id) ...
        ' get the highest score ' , num2str(score_valid) ]);
    
    score_record(epoch_id,1) = score_valid;
    score_record(epoch_id,end) = max_cand_id;
    
    
    sel_id = [sel_id max_cand_id];
                               
    
    for i = 1:max_bag_num
        temp_feat_train{i} = feat_train{i}( :,sel_id);
    end
    
    parfor i = 1:max_bag_num                    
        warning off
        opt = statset('UseParallel','always');            
        temp_bag = TreeBagger(num_treebagger, ...
            temp_feat_train{i}, lab_train{i},'Options',opt);
        bag{i} = temp_bag;
        warning on
    end
        
    
    for j = 1:length(test_video)
        
        f_on_this_test_bag = zeros(1,max_bag_num);
        
        for i = 1:max_bag_num
            temp_feat_test = feat_test{i,j}(:,sel_id);
            temp_lab_test = lab_test{i,j};
            
            sum_lab_valid = sum( temp_lab_test );        
            t_lab_valid = temp_lab_test==1;
            
            f_on_this_bag = zeros(1,max_bag_num);
            
            parfor bag_id = 1:max_bag_num                    
                res_str = bag{bag_id}.predict( temp_feat_test);
                n = length(res_str);
                res = zeros(1,n);
                for j = 1:n
                    res(j) = str2num(res_str{j});    
                end
                tp = sum(res(t_lab_valid));
                precision = tp / (sum( res)+1e-3);
                recall = tp / sum_lab_valid;
                f_on_this_bag( bag_id ) = precision * 2 * recall ...
                    / (recall + precision +1e-3);
            end            
           
            f_on_this_test_bag(i) = mean(f_on_this_bag);
            
        end
        
        disp(['test on video ' , test_video{j} ,...
            ' get ' ,num2str(mean(f_on_this_test_bag))] )
        
        score_record(epoch_id,j+1) = mean(f_on_this_test_bag);                
    end
    
    dlmwrite('report_feature_selection.txt',score_record,...
            'delimiter','\t','newline','pc');
    
    
    disp('===============')    
    
end

%%

matlabpool close